package ua.kpi.JavaTraning5;

import java.util.Scanner;

/**
 * This class includes methods for finding the column in the result of the division.
 *
 * @author Vitaliy Vasylenko <apa4i007@gmail.com>
 * @version 1.5
 * @since 2013-05-15
 */
public class LongDivision {

    /**
     * The main method to run the program.
     *
     * @param args - passed arguments
     */
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int dividend = readValue(scanner, "Enter dividend: ");
        int divider = readValue(scanner, "Enter divider: ");
        System.out.println("----------------------------");
        System.out.print(dividend);
        System.out.println(printGraphicsForDivision(divider, getWholePartOfAnswer(divide(dividend, divider))));
        System.out.println(calculateLongDivisionStepByStep(dividend, divider));
    }

    /**
     * Read the value from the scanner.
     *
     * @param scanner - Scanner where to read
     * @param hint    - Prompt appears when you enter the wrong numbers
     * @return int - The number entered from the console
     */
    public static int readValue(Scanner scanner, String hint) {
        System.out.println(hint);
        int value = 0;
        try {
            value = scanner.nextInt();
            if (!isNotNull(value)) {
                System.out.println("Input <= 0, try again!");
                System.exit(0);
            }
        } catch (Exception e) {
            System.out.println("Invalid input, try again!");
            System.exit(0);
        }
        return value;
    }

    /**
     * Check for zero.
     *
     * @param value - The value for verification
     * @return boolean - true if value > 0, otherwise false
     */
    public static boolean isNotNull(int value) {
        return value > 0;
    }

    /**
     * The method of dividing the two numbers.
     *
     * @param dividend - The value of the dividend
     * @param divider  - The value of the divisor
     * @return int[] - An array of found answers
     */
    public static int[] divide(int dividend, int divider) throws NumberFormatException {
        String dividendInSymbols = String.valueOf(dividend);
        int[] arrayOfAnswers = new int[dividendInSymbols.length()];
        int restFromOneIteration = 0;
        for (int i = 0; i < dividendInSymbols.length(); i++) {
            arrayOfAnswers[i] = getMainPartFromDivider(restFromOneIteration, dividendInSymbols, divider);
            restFromOneIteration = getLastFromDivided(restFromOneIteration, dividendInSymbols, arrayOfAnswers[i], divider);
        }
        return arrayOfAnswers;
    }

    /**
     * The method returns the main part of the division.
     *
     * @param arrayOfAnswers - An array of found answers from divide
     * @return int - The main part of the division
     */
    private static int getWholePartOfAnswer(int[] arrayOfAnswers) {
        int answer = 0;
        for (int i = 0; i < arrayOfAnswers.length; i++) {
            answer = Integer.parseInt(answer + String.valueOf(arrayOfAnswers[i]));
        }
        return answer;
    }

    /**
     * The method returns the main part of the divider.
     *
     * @param restFromOneIteration - The result from the previous iteration of division
     * @param symbols              - The dividend is translated into symbols
     * @param divider              - The value of the divisor
     * @return int - The main part of the divider
     */
    public static int getMainPartFromDivider(int restFromOneIteration, String symbols, int divider) throws NumberFormatException {
        return Integer.parseInt(restFromOneIteration + String.valueOf(symbols.charAt(0))) / divider;
    }

    /**
     * The method returns the last part of the division.
     *
     * @param lastFromOneIteration - The last from the previous iteration of division
     * @param symbols              - The dividend is translated into symbols
     * @param resultOnOneIteration - The result from the previous iteration of division
     * @param divider              - The value of the divisor
     * @return int - The last part of the divider
     */
    public static int getLastFromDivided(int lastFromOneIteration, String symbols, int resultOnOneIteration, int divider) throws NumberFormatException {
        return Integer.parseInt(lastFromOneIteration + String.valueOf(symbols.charAt(0))) - resultOnOneIteration * divider;
    }


    /**
     * The method calculates the division step by step.
     *
     * @param dividend - The value of the dividend
     * @param divider  - The value of the divisor
     * @return String - Long division step by step
     */
    public static String calculateLongDivisionStepByStep(int dividend, int divider) {
        String dividendInSymbols = String.valueOf(dividend);
        int lastFromOneIteration = 0;
        String out = "";
        for (int i = 0; i < dividendInSymbols.length(); i++) {
            int resultOnOneIteration = getMainPartFromDivider(lastFromOneIteration, dividendInSymbols, divider);
            lastFromOneIteration = getLastFromDivided(lastFromOneIteration, dividendInSymbols, getMainPartFromDivider(lastFromOneIteration, dividendInSymbols, divider), divider);
            out = out + String.valueOf(resultOnOneIteration * divider + "\n");
            if (i == dividendInSymbols.length() - 1) {
                break;
            } else {
                out = out + String.valueOf(lastFromOneIteration + String.valueOf(dividendInSymbols.charAt(0)) + "\n");
            }
        }
        return out + lastFromOneIteration;
    }

    /**
     * The method returns formatted line for the printing in console.
     *
     * @param divider - The value of the divisor
     * @param answer  - The answer from divide two numbers
     * @return String - The formatted line
     */
    public static String printGraphicsForDivision(int divider, int answer) {
        String print = "|_" + divider + "_" + "\n" + "" + "    " + answer;
        return print;
    }

}
